package com.anxpp.calculator.bio;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**http://blog.anxpp.com/index.php/archives/895/
 *   final修饰类表示这个类不能继承
 *   BIO服务器端源码
 *   @author lijun
 *   @version 1.0
 */
public final class Server {
    //默认的端口号
    private static int DEFAULT_PORT = 12345;
    //单例的ServerSocket
    private static ServerSocket server;
    //根据传入参数设置监听端口，如果没有参数调用以下方法并使用默认值
    public static void start() throws IOException{
        //使用默认值
        start(DEFAULT_PORT);
    }

    //这个方法不会被大量并发访问，不太需要考虑效率，直接进行方法同步就行了

    /**
     * synchronized关键字介绍：Java中的Synchronized关键字来标记一个方法或者一个代码块就可以实现资源的同步。
     * 在多线程环境中，对象的所有synchronized方法一次只能被一个线程访问，
     * 其它所有访问同步块的线程会被一直阻塞直到同步块中的线程退出。
     * @param port
     * @throws IOException
     */
    private synchronized static void start(int port) throws IOException{
        if(server != null) return;
        try{
            //构造函数创建ServerSocket
            //如果端口合法且空闲，服务端就监听成功
            server = new ServerSocket(port);
            System.out.println("服务器已启动，端口号：" + port);
//            System.out.println("------------------------------------");
            Socket socket;
            //通过无限循环监听客户端连接
            //如果没有客户端接入，将阻塞在accept操作上
            while(true){
                socket = server.accept();
                //当有新的客户端接入时，执行下面的代码
                //然后创建一个新的线程处理这条socket链路
                //每收到一个请求，就启动一个线程去处理，线程自己负责接收流数据
                new Thread(new ServerHandler(socket)).start();
            }
        }finally{
            //一些必要的清理工作
            if(server != null){
                System.out.println("服务器已关闭。");
                server.close();
                server = null;
                System.out.println("------------------------------------");
            }
        }

    }

    public static void main(String args[]) throws IOException {
        Server.start();
    }


}

